﻿using System;
using System.ComponentModel;
using System.Windows.Controls;
using Notoric.Gui.Windows;

namespace Notoric.Gui.Commands
{
    /// <summary>
    /// Implements a command for inserting a new dynamic mark into a Common Western Music Notations section.
    /// </summary>
    public class InsertDynamicMarkCommand : RibbonCommand
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="InsertDynamicMarkCommand"/> class.
        /// </summary>
        /// <param name="mainWindow">
        /// <para>
        /// Type: <see cref="MainWindow"/>
        /// </para>
        /// <para>
        /// The main application window.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="mainWindow"/> is <see langword="null"/>.
        /// </exception>
        public InsertDynamicMarkCommand(MainWindow mainWindow)
            : base(mainWindow)
        {
            ScreenTipTitle = "Insert Dynamic Mark";
            ScreenTipText = "Inserts a new dynamic mark to the composition.";

            mainWindow.DocumentPane.SelectionChanged += new SelectionChangedEventHandler(DocumentPane_SelectionChanged);
        }

        #endregion

        #region ICommand Members

        /// <inheritdoc/>
        public override bool CanExecute(object parameter)
        {
            return (ApplicationWindow.ActivePage != null && ApplicationWindow.ActivePage.SelectedContent == ViewModel.Elements.SelectedContentType.Music)
                || (ApplicationWindow.DocumentPane.SelectedItem is LinearCompositionViewPanel);
        }

        /// <inheritdoc/>
        public override void Execute(object parameter)
        {
            ViewModel.Elements.CWNotation.DynamicMarkType markType = ViewModel.Elements.CWNotation.DynamicMarkType.Piano;
            byte degree = 1;

            if (parameter != null)
            {
                var values = parameter.ToString().Split(',');
                if (values.Length == 2)
                {
                    markType = (ViewModel.Elements.CWNotation.DynamicMarkType)Enum.Parse(typeof(ViewModel.Elements.CWNotation.DynamicMarkType), values[0]);
                    degree = byte.Parse(values[1]);
                }
            }

            var cmd = new ViewModel.AddDynamicMarkCommand(ApplicationWindow.StackManager.ActiveUndoStack, ApplicationWindow.StackManager.ActiveRedoStack)
            {
                Degree = degree,
                MarkType = markType
            };

            var appState = ((App)App.Current).CurrentState;
            appState.Command = cmd;
            appState.StatusBarMessage = "Select the durational symbol to which the dynamic mark will be attached.";
            appState.MouseTarget = typeof(View.Music.CWNotation.Controls.MusicSectionInterior);
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the selected document has changed.
        /// </summary>
        /// <param name="sender">Object where the event handler is attached</param>
        /// <param name="e">Event data</param>
        private void DocumentPane_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (activePage != null)
            {
                activePage.PropertyChanged -= activePage_PropertyChanged;
                activePage = null;
            }

            if (ApplicationWindow.ActivePage != null)
            {
                activePage = ApplicationWindow.ActivePage;
                activePage.PropertyChanged += new PropertyChangedEventHandler(activePage_PropertyChanged);
            }

            RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Occurs when a property of the active page has changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void activePage_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "SelectedContent")
                RaiseCanExecuteChanged();
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the currently active page.
        /// </summary>
        private ViewModel.Elements.Page activePage;

        #endregion
    }
}
